package cn.fl.custpay.service.impl;

import cmm.comm.facade.syssms.api.ISmsAddApiService;
import cmm.comm.facade.syssms.dto.SmsSendParamDTO;
import cmm.mid.core.framework.dto.*;
import cmm.mid.core.framework.dto.DataResultDTO;
import cmm.mid.core.framework.page.Pager;
import cmm.user.facade.system.api.ISysUsrApiService;
import cmm.user.facade.system.dto.SysUsrDTO;
import cn.cmm.base.framework.constant.BaseConstant;
import cn.cmm.base.framework.constant.BaseExceptionConstant;
import cn.cmm.base.framework.exception.BaseException;
import cn.cmm.base.framework.utils.*;
import cn.fl.customer.transform.CstBankVOTransform;
import cn.fl.customer.vo.CstBankVO;
import cn.fl.custpay.api.ICmmOlAutoCharRecApiService;
import cn.fl.custpay.api.ICstSignedBankApiService;
import cn.fl.custpay.condition.CmmOlAutoChargeQueryCondition;
import cn.fl.custpay.dto.*;
import cn.fl.custpay.service.ICmmBindingCartService;
import cn.fl.custpay.service.ICmmOlWithholdingApiService;
import cn.fl.custpay.service.ICmmRechargeRecordService;
import pay.business.facade.custpay.api.IBankCardApiService;
import cn.fl.framework.base.context.CurrentThreadContext;
import cn.fl.framework.constant.DictionaryConstant;
import cn.fl.system.service.ISysUsrService;
import cn.fl.system.vo.SysUsrVO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import fl.constant.facade.framework.constant.CmmCustPayConstant;
import fl.customer.facade.customer.api.ICustomerApiService;
import fl.customer.facade.customer.api.ICustomerQueryApiService;
import fl.customer.facade.customer.condition.CstBscInfoQueryCondition;
import fl.customer.facade.customer.dto.CstBankDTO;
import fl.customer.facade.customer.dto.CstBscInfoDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pay.business.facade.custpay.api.IPayAutoSetRuleApiService;

import java.util.*;
import java.util.concurrent.Executors;

/**
 * @ClassName CmmBindingCartServiceImp
 * @Description TODO
 * @Author shijb
 * @Date 2018/7/6 13:59
 * @Version 1.0
 **/
@Service
public class CmmBindingCartServiceImp implements ICmmBindingCartService {

    /**
     * 日志
     */
    private static final Logger logger = LoggerFactory.getLogger(ICmmBindingCartService.class);
    @Autowired
    private ICstSignedBankApiService cstSignedBankApiService;
    @Autowired
    private ICustomerQueryApiService customerQueryApiService;
    @Autowired
    private ICustomerApiService customerApiService;
    @Autowired
    private ICmmRechargeRecordService cmmRechargeRecordService;
    @Autowired
    private ICmmOlWithholdingApiService cmmOlWithholdingApiService;
    @Autowired
    private ICmmOlAutoCharRecApiService cmmOlAutoCharRecApiService;
    @Autowired
    private ISysUsrService sysUsrService;
    /**
     * 用户接口服务
     */
    @Autowired
    private ISysUsrApiService sysUsrApiService;
    /**
     * 短信接口
     */
    @Autowired
    private ISmsAddApiService smsAddApiService;
    /**
     * 绑卡服务
     */
    @Autowired
    private IBankCardApiService bankCardApiService;

    @Autowired
    private IPayAutoSetRuleApiService payAutoSetRuleApiService;
    /**
     * 账号截取长度
     */
    private static final Integer ACCOUNT_SUB_LENGTH = 4;

    @Override
    public Pager searchListPage(Pager page) throws BaseException {
        if (null == page) return new Pager();
        //获取客户开户银行信息列表
        Pager resultpager = this.customerQueryApiService.searchCstBankListPage(page);
        List<CstBankVO> list = CstBankVOTransform.toVOList((List<CstBankDTO>) resultpager.getResultList());

        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> ids = new ArrayList<>();
            for (CstBankVO cstBankVO : list) {
                Long id = cstBankVO.getId();//银行信息主键
                ids.add(id);
            }

            if (CollectionUtils.isNotEmpty(ids)) {
                //查询银行卡自动代扣开启列表
                List<CmmOlAutoChargeDTO> cmmOlAutoChargeDTOList = this.cmmOlWithholdingApiService.searchCmmOlAutoChargeListByBankIds(ids);
                //根据银行主键列表查询对应签约信息
                List<CstSignedBankDTO> cstSignedBankDTOList = this.cstSignedBankApiService.searchListByBankIds(ids);
                //数据字典：三方支付平台/渠道
                Map<String, String> dictionryMap = cmmRechargeRecordService.getDictionryMap(cmm.user.facade.framework.constant.DictionaryConstant.SYS_PAY_CHANNEL_CD);
                //数据字典：证件类型组值
                Map<String, String> codeGrpCertTypeMap = cmmRechargeRecordService.getDictionryMap(DictionaryConstant.CODE_GRP_CERT_TYP_CD);
                //数据字典：客户自然人 开户银行
                Map<String, String> codeGrpSysBkLvlMap = cmmRechargeRecordService.getDictionryMap(DictionaryConstant.CODE_GRP_CST_NP_BK_CD);

                for (CstBankVO cstBankVO : list) {
                    Long id = cstBankVO.getId();//银行信息主键
                    String signNo = cstBankVO.getSignNo();
                    //List<CstSignedBankDTO> newList = new ArrayList<>();
                    String payTypeName = "";
                    if (StringUtils.isNotEmpty(signNo)) {//整合银行信息表中签约支付
                        payTypeName = "信联";
                    }
                    /**
                     * 判断银行卡是否已设置自动代扣
                     **/
                    Integer isAuto = 0;
                    Date crtOlAutoDate = null;
                    if (CollectionUtils.isNotEmpty(cmmOlAutoChargeDTOList)) {
                        for (CmmOlAutoChargeDTO cmmOlAutoChargeDTO : cmmOlAutoChargeDTOList) {
                            if (id != null && id.equals(cmmOlAutoChargeDTO.getBankId())) {
                                isAuto = cmmOlAutoChargeDTO.getIsAuto();
                                crtOlAutoDate = cmmOlAutoChargeDTO.getCrtTm();
                                break;
                            }
                        }
                    }
                    cstBankVO.setIsAuto(isAuto);
                    cstBankVO.setCrtOlAutoDate(crtOlAutoDate);
                    /**
                     * 整理同一银行卡下的签约关联数据
                     **/
                    if (CollectionUtils.isNotEmpty(cstSignedBankDTOList)) {
                        for (CstSignedBankDTO cstSignedBankDTO : cstSignedBankDTOList) {
                            Long bankId = cstSignedBankDTO.getBankId();//客户银行签约表关联银行id
                            if (id.equals(bankId)) {
                                //newList.add(cstSignedBankDTO);
                                if (StringUtils.isNotEmpty(payTypeName)) {
                                    payTypeName += "," + dictionryMap.get(String.valueOf(cstSignedBankDTO.getPayType()));
                                } else {
                                    payTypeName += dictionryMap.get(String.valueOf(cstSignedBankDTO.getPayType()));
                                }
                            }
                        }
                    }
                    //将关联数据列表添加进银行信息对象中
                    /*if(CollectionUtils.isNotEmpty(newList)){
                        cstBankVO.setCstSignedBankList(newList);
                    }*/
                    cstBankVO.setPayTypeName(payTypeName);
                    //证件类型转换
                    cstBankVO.setCertTypCd(codeGrpCertTypeMap.get(cstBankVO.getCertTypCd()));
                    //银行类型转换
                    cstBankVO.setBkCdNm(codeGrpSysBkLvlMap.get(cstBankVO.getBkCd()));
                }
            }
        }
        resultpager.setResultList(list);
        return resultpager;
    }

    @Override
    public CstBankVO selectById(Long id) {
        return CstBankVOTransform.toVO(customerApiService.selectCstBankById(id));
    }

    @Override
    public boolean modify(CstBankVO entity) {
        if (null == entity) {
            BaseLogUtils.info(logger, "modify", "修改对象参数不能为空!", CurrentThreadContext.getCurrentUserName());
            return false;
        }
        return customerApiService.modifyCstBankDTO(CstBankVOTransform.toDTO(entity));
    }

    @Override
    public boolean removeById(CstBankVO vo) {
        if (null == vo) {
            BaseLogUtils.info(logger, "removeById", "删除客户开户行参数不能为空!", CurrentThreadContext.getCurrentUserName());
            return false;
        }
        boolean succ = false;
        /**
         * 删除支付系统卡数据
         */
        DataResultDTO resultDTO =  this.bankCardApiService.deleteBank(vo.getId());
        BaseLogUtils.newWebLogger("删除支付卡数据返回："+ JSON.toJSONString(resultDTO)).info();
        if(null == resultDTO){
            return succ;
        }
        if(BaseConstant.IS_YESNO_YES == resultDTO.getSuccess()){
            succ = (boolean)resultDTO.getData();
        }else{
            BaseLogUtils.newWebLogger("删除数据失败："+ resultDTO.getInfo() + ";id = " + vo.getId()).info();
        }

        if (succ) {
            //更新操作人
            succ = customerApiService.modifyCstBankDet(CstBankVOTransform.toDTO(vo));
            //cstSignedBankApiService.deleteByBankId(vo.getId());//删除关联签约信息
        }
        return succ;
    }

    @Override
    public boolean autoChargeOperate(String id, String cstId, String isAuto, Long currentUserId) throws BaseException {
        boolean issuccess = false;
        try {
            Long bankId = Long.valueOf(id);
            Integer isAutoInt = Integer.valueOf(isAuto);
            Date currentDate = new Date();
            /**
             * 开启自动代扣卡前，需要校验卡是否符合自动代扣卡设置规则
             */
            if(BaseConstant.IS_YESNO_YES_STR.equals(isAuto)){
                boolean isSuccess =  payAutoSetRuleApiService.rule(bankId, true);
                if(!isSuccess){
                    BaseLogUtils.newWebLogger("设置失败，该卡不符合自动代扣卡设置规则！" ).info();
                    throw new BaseException(BaseExceptionConstant.COMMON_0002, "设置失败，该卡不符合自动代扣卡设置规则!");
                }
            }
            //判断是否首次设置自动代扣
            CmmOlAutoChargeQueryCondition queryCondition = new CmmOlAutoChargeQueryCondition();
            queryCondition.setBankId(Long.valueOf(id));
            queryCondition.setCstId(cstId);
            List<CmmOlAutoChargeDTO> cmmOlAutoChargeDTOList = cmmOlWithholdingApiService.searchCmmOlAutoChargeList(queryCondition);
            //根据银行id获取对象
            CstBankDTO cstBankDTO = customerApiService.selectCstBankById(bankId);
            //首次设置自动代扣，新增
            if (CollectionUtils.isEmpty(cmmOlAutoChargeDTOList)) {
                CmmOlAutoChargeDTO cmmOlAutoChargeDTO = new CmmOlAutoChargeDTO();
                cmmOlAutoChargeDTO.setBankId(bankId);
                cmmOlAutoChargeDTO.setCstId(cstId);
                cmmOlAutoChargeDTO.setIsAuto(isAutoInt);
                cmmOlAutoChargeDTO.setIsDel(0);
                //cmmOlAutoChargeDTO.setCrtTm(currentDate);
                if (cstBankDTO != null) {
                    cmmOlAutoChargeDTO.setClientName(cstBankDTO.getAccNm());
                    cmmOlAutoChargeDTO.setClientPhone(cstBankDTO.getCardTel());
                } else {
                    BaseLogUtils.info(logger, "autoChargeOperate", "获取客户开户银行对象失败.[bankId=" + bankId + "]", CurrentThreadContext.getCurrentUserName());
                }
                issuccess = cmmOlWithholdingApiService.addCmmOlAutoCharge(cmmOlAutoChargeDTO) > 0;
            } else {//否则，更新
                CmmOlAutoChargeDTO cmmOlAutoChargeDTO = cmmOlAutoChargeDTOList.get(0);
                cmmOlAutoChargeDTO.setIsAuto(isAutoInt);
                cmmOlAutoChargeDTO.setMdfTm(currentDate);
                issuccess = cmmOlWithholdingApiService.modifyCmmOlAutoCharge(cmmOlAutoChargeDTO);
            }
            if (issuccess) {
                CstBscInfoDTO cstBscInfoDTO = this.customerApiService.selectCstBscInfoById(Long.valueOf(cstId), "0000");
                CmmOlAutoCharRecDTO cmmOlAutoCharRecDTO = new CmmOlAutoCharRecDTO();
                cmmOlAutoCharRecDTO.setCstId(cstId);
                cmmOlAutoCharRecDTO.setBkCd(cstBankDTO.getBkCd());
                //数据字典：客户自然人 开户银行
                Map<String, String> codeGrpSysBkLvlMap = cmmRechargeRecordService.getDictionryMap(DictionaryConstant.CODE_GRP_CST_NP_BK_CD);
                cmmOlAutoCharRecDTO.setAccOrgNm(codeGrpSysBkLvlMap.get(cstBankDTO.getBkCd()));
                cmmOlAutoCharRecDTO.setAccNo(cstBankDTO.getAccNo());
                cmmOlAutoCharRecDTO.setIsAuto(isAutoInt);
                cmmOlAutoCharRecDTO.setPlatformCd("3");
                cmmOlAutoCharRecDTO.setCrtUsrId(currentUserId);
                cmmOlAutoCharRecDTO.setMdfUsrId(currentUserId);
                if (cstBscInfoDTO != null) {
                    cmmOlAutoCharRecDTO.setClientName(cstBscInfoDTO.getCstNm());
                    Long usrId = cstBscInfoDTO.getUsrId();
                    try {
                        SysUsrVO sysUsrVO = this.sysUsrService.selectById(usrId, CurrentThreadContext.getCurrentSysCd());
                        if (sysUsrVO != null) {
                            cmmOlAutoCharRecDTO.setClientPhone(sysUsrVO.getMp());
                        }
                    } catch (Exception e) {
                        BaseLogUtils.info(logger, "autoChargeOperate", "获取用户失败! " + usrId + e.getMessage(), e);
                    }
                }
                cmmOlAutoCharRecDTO.setCrtTm(currentDate);
                cmmOlAutoCharRecDTO.setMdfTm(currentDate);
                this.cmmOlAutoCharRecApiService.add(cmmOlAutoCharRecDTO);
            }
        } catch (BaseException e) {
            BaseLogUtils.newWebLogger(e.getMessage()).error(BaseExceptionConstant.COMMON_0002,e);
            throw new BaseException(BaseExceptionConstant.COMMON_0002, e.getMessage());
        } catch (Exception e) {
            BaseLogUtils.newWebLogger("设置自动代扣异常!" + e.getMessage()).error(BaseExceptionConstant.COMMON_0002,e);
            throw new BaseException(BaseExceptionConstant.COMMON_0002, "设置自动代扣异常!");
        }
        return issuccess;
    }

    @Override
    public boolean sendSMS(JSONArray paramJsonList) throws BaseException {
        try {
            if (paramJsonList != null && paramJsonList.size() > 0) {
                List<Long> cstIdList = new ArrayList<>();
                List<Long> usrIdList = new ArrayList<>();
                Map<Long, String> accNoMap = new HashMap<>(32);
                for (int i = 0; i < paramJsonList.size(); i++) {
                    JSONObject paymentjson = JSONObject.parseObject(paramJsonList.get(i).toString());
                    //银行卡号
                    String accNo = paymentjson.get("accNo") != null ? paymentjson.getString("accNo") : "";
                    //客户id
                    String cstId = paymentjson.get("cstId") != null ? paymentjson.getString("cstId") : "";
                    //预留手机号
                    String cardTel = paymentjson.get("cardTel") != null ? paymentjson.getString("cardTel") : "";
                    if (StringUtils.isNotEmpty(cstId)) {
                        Long id = Long.valueOf(cstId);
                        cstIdList.add(id);
                        accNoMap.put(id, accNo);
                    }
                }
                //根据客户ids集合查询客户对象列表
                CstBscInfoQueryCondition condition = new CstBscInfoQueryCondition();
                condition.setIds(cstIdList);
                List<CstBscInfoDTO> cstBscInfoDTOS = this.customerQueryApiService.searchCstBscInfoList(condition);
                //封装用户Ids集合
                if (CollectionUtils.isNotEmpty(cstBscInfoDTOS)) {
                    for (CstBscInfoDTO cstBscInfoDTO : cstBscInfoDTOS) {
                        Long usrId = cstBscInfoDTO.getUsrId();
                        Long id = cstBscInfoDTO.getId();
                        if (StringUtils.isNotEmpty(usrId)) {
                            usrIdList.add(usrId);
                            accNoMap.put(usrId, accNoMap.get(id));
                        }
                    }
                }
                //根据用户ids集合查询用户对象列表
                List<SysUsrDTO> sysUsrDTOS = this.sysUsrApiService.selectSysUserInfoList(usrIdList);
                BaseLogUtils.info(logger, "sendSMS", "需要发送短信用户列表" + JSON.toJSONString(sysUsrDTOS));
                if (CollectionUtils.isNotEmpty(sysUsrDTOS)) {
                    for (SysUsrDTO sysUsrDTO : sysUsrDTOS) {
                        //用户登录手机号
                        String mp = sysUsrDTO.getMp();
                        Long usrid = sysUsrDTO.getId();
                        this.sendShortMsg(mp, accNoMap.get(usrid));
                    }
                }
            } else {
                BaseLogUtils.info(logger, "sendSMS", "请选择银行卡");
                throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_600, "请选择银行卡!");
            }
        }catch (Exception e){
            BaseLogUtils.info(logger, "sendSMS", "银行卡补全信息选发短信异常。" + e.getMessage(),e);
            throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_700, "系统异常!");
        }

        return true;
    }

    @Override
    public boolean batchSendSMS() throws BaseException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                execute();
            }
        }).start();

        return true;
    }

    private void execute() {
        BaseLogUtils.info(logger, "execute", "银行卡补全信息群发短信----开始。");
        try {
            List<CstBankDTO> cstBankDTOS = this.customerQueryApiService.searchCardMissingInfoList();
            if (CollectionUtils.isNotEmpty(cstBankDTOS)) {
                for (CstBankDTO dto : cstBankDTOS) {
                    try{
                        Long usrId = dto.getUsrId();
                        if(StringUtils.isNotEmpty(usrId)){
                            //用户登录手机号
                            SysUsrDTO sysUsrDTO = this.sysUsrApiService.selectSysUsrById(usrId,"11000","0000");
                            if(null != sysUsrDTO){
                                String mp = sysUsrDTO.getMp();
                                String accNo = dto.getAccNo();
                                this.sendShortMsg(mp, accNo);
                            }

                        }
                    }catch (Exception e){
                        BaseLogUtils.info(logger, "sendSMS", "银行卡补全信息群发短信异常。" + e.getMessage(),e);
                    }
                }
            }
        }catch (Exception e){
            BaseLogUtils.info(logger, "sendSMS", "银行卡补全信息群发短信异常。" + e.getMessage(),e);
            throw new BaseException(BaseExceptionConstant.BASE_EXCEPTION_CODE_700, "系统异常!");
        }
        BaseLogUtils.info(logger, "execute", "银行卡补全信息群发短信----结束。");
    }

    /**
     * @MethodName sendShortMsg
     * @Description: TODO 银行卡信息补全发送短信
     * @Author: shijibin@lionbridgecapital.cn
     * @CreateDate: 2019/3/1 11:08
     * @Version: 1.0.0
     * @Param phone
     * @Param accNo
     * @Return void
     * @UpdateRemark [序号][YYYY-MM-DD] [更改人姓名][变更描述]
     */
    private void sendShortMsg(String phone,String accNo) {
        try {

            String endNo = "";
            if (accNo.length() > ACCOUNT_SUB_LENGTH) {
                endNo = accNo.substring(accNo.length() - 4);
            }
            SmsSendParamDTO smsSendParamDTO = new SmsSendParamDTO();
            smsSendParamDTO.setCode(CmmCustPayConstant.CMM_SHORT_CODE_115);
            smsSendParamDTO.setMp(phone);

            smsSendParamDTO.setParams(new String[]{endNo});
            smsSendParamDTO.setType(0);
            cmm.mid.core.framework.dto.DataResultDTO resultDTO = this.smsAddApiService.sendSMS(smsSendParamDTO);
            if(BaseConstant.IS_YESNO_YES_STR.equals(resultDTO.getCode())){
                BaseLogUtils.info(logger, "sendShortMsg", "银行卡信息补全发送短信成功： phone="+phone );
            }else{
                BaseLogUtils.info(logger, "sendShortMsg", "银行卡信息补全发送短信失败： "+resultDTO.getInfo());
            }
        }catch (Exception e){
            BaseLogUtils.info(logger, "sendShortMsg", "银行卡信息补全发送短信异常： " + e.getMessage(), e);
        }
    }

}
